#pragma once

#include "shared\dbg.h"


typedef void * cparam_t;//custom param type

typedef unsigned int exec_id_t; //process id type

interface console_callback_t{
	//on stdout & stderr output
	virtual void on_stdout_line(exec_id_t id, cparam_t param,const std::string  & str)= 0;
	virtual void on_stderr_line(exec_id_t id, cparam_t param,const std::string  & str)= 0;

	//on exit
	virtual void on_exit(exec_id_t id, int code){};
};





struct exec_context_t{
	//exec_id_t proc_id;
	DWORD thread_id;

	bool support_stdin;

	HANDLE h_stdin;
	std::string program;
	std::string args;
	std::string workdir;
	

	console_callback_t *parser;
	cparam_t param;//callback param
	std::string out_buf;
	std::string err_buf;


	HANDLE h_thread;
	
	PROCESS_INFORMATION pi;
	
	bool exited;

};


class Executor{
private:
	static std::vector<exec_context_t*> m_ctxs;
	static std::map<exec_id_t,std::string> m_cmds;
	static CRITICAL_SECTION cs_cmd;


	static Executor *self;
	Executor();

	static void check_exes();
	
public:

	~Executor();

	static Executor* Instance(){
		if(self == NULL)
			self = new Executor();
		return self;
	}

	//start a process 
	static exec_id_t exec(char *exe,char *params, char *workdir,console_callback_t *parser,cparam_t data, bool support_stdin = false);
	static int pause(exec_id_t proc);
	static int stop(exec_id_t proc);
	static int resume(exec_id_t proc);
	static void process_command();


	//command sub-process
	static bool command(exec_id_t proc,const char *cmd);

	
};